#include <syncupconfig.h>
#include <async_queue.h>
#include <stdio.h>
#include <pthread.h>
#ifdef OS_WIN
#include <windows.h>
#else
#include <sys/select.h>
#endif

static inline void thread_msleep(int msecs)
{
#ifdef OS_WIN
    Sleep(msecs);
#else
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = msecs * 1000;
    select(0, NULL, NULL, NULL, &tv);
#endif
}

static struct async_queue queue = ASYNC_QUEUE_INITIALIZER(queue);

void *
thread_func(void *thread_name)
{
    const char *name = (const char *) thread_name;
    long data;
    while (1) {
        data = (long) async_queue_pop(&queue);
        if (data == 0) {
            printf("queue interrupted in %s\n", name);
            break;
        }
        printf("%s get data: %ld\n", name, data);
    }
    return NULL;
}

#define THREAD_SIZE 3

int main()
{
    pthread_t tid[THREAD_SIZE];
    char thread_name[THREAD_SIZE][20];
    long data;
    int i;
    for (i = 0; i < 3; ++i) {
        sprintf(thread_name[i], "thread %d", i + 1);
        pthread_create(&tid[i], NULL, thread_func, thread_name[i]);
    }
    while (1) {
        printf("Enter data: ");
        if (scanf("%ld", &data) != 1) {
            puts("");
            break;
        }
        async_queue_push(&queue, (void *)data);
        thread_msleep(100);
    }
    async_queue_interrupt(&queue);
    for (i = 0; i < THREAD_SIZE; ++i) {
        pthread_join(tid[i], NULL);
    }
    return 0;
}
